package search

// this package is not used, as this approach is too time consuming
/*
import (
	b "code.google.com/p/gochess/board"
	pos "code.google.com/p/gochess/position"
	"fmt"
)

var MoveDirections = [16]b.Square{
	// ranks and files - bit 1-2
	b.UP, b.DOWN, b.LEFT, b.RIGHT,
	// diagonal - bit 3-4
	b.UP + b.RIGHT, b.DOWN + b.LEFT, b.UP + b.LEFT, b.DOWN + b.RIGHT,
	// knight move directions - bit 5-8
	2*b.UP + b.RIGHT, b.UP + 2*b.RIGHT,
	b.DOWN + 2*b.RIGHT, 2*b.DOWN + b.RIGHT,
	2*b.DOWN + b.LEFT, b.DOWN + 2*b.LEFT,
	b.UP + 2*b.LEFT, 2*b.UP + b.LEFT,
}

// SlideDirections[i] == -SlideDirections[7-i]!
var SlideDirections = [8]b.Square{
	b.UP,
	b.LEFT,
	b.UP + b.RIGHT,
	b.UP + b.LEFT,
	b.DOWN + b.RIGHT,
	b.DOWN + b.LEFT,
	b.RIGHT,
	b.DOWN,
}

var SliderIndexBitMasks = map[b.Square]int{
	b.UP:             0x01,
	b.LEFT:           0x02,
	b.UP + b.RIGHT:   0x04,
	b.UP + b.LEFT:    0x08,
	b.DOWN + b.RIGHT: 0x10,
	b.DOWN + b.LEFT:  0x20,
	b.RIGHT:          0x40,
	b.DOWN:           0x80,
}

// for knights, we need: directions bitmask -> []b.Square, so we have all locations for there
// capture moves
// todo: the keys are wrong? copy&paste error?

var IndexBitMasks = map[b.Square]int{
	b.UP:             0x01,
	b.LEFT:           0x02,
	b.UP + b.RIGHT:   0x04,
	b.UP + b.LEFT:    0x08,
	b.DOWN + b.RIGHT: 0x10,
	b.DOWN + b.LEFT:  0x20,
	b.RIGHT:          0x40,
	b.DOWN:           0x80,
}


// attacks of one piece type on a square
type PieceAttacks struct {
	directions int
	number     int
}

// all attacks on a square
type SquareAttacks struct {
	sliderAttacks PieceAttacks
	knightAttacks PieceAttacks
	pawnAttacks   PieceAttacks
	attacks       int
}

// one for each player
type AttackBoard struct {
	attacks [b.NUMBER_OF_SQUARES]SquareAttacks
}

func (this *AttackBoard) NumberOfAttackers(location b.Square) int32 {
	return this.attacks[location].attacks
}

func (this *AttackBoard) SetSliderAttack(location b.Square, bitmask int) {

	this.attacks[location].sliderAttacks.directions |= bitmask
}

// todo: second parameter should have its own type
func (this *AttackBoard) SetKnightAttack(location b.Square, bitmask int) {

	this.attacks[location].knightAttacks.directions |= bitmask
}

// todo: second parameter should have its own type
func (this *AttackBoard) SetPawnAttack(location b.Square, bitmask int) {

	this.attacks[location].pawnAttacks.directions |= bitmask
}

func (this *AttackBoard) SliderAttacks(location b.Square) PieceAttacks {
	return this.attacks[location].sliderAttacks
}

func (this *AttackBoard) KnightAttacks(location b.Square) PieceAttacks {
	return this.attacks[location].knightAttacks
}

func (this *AttackBoard) PawnAttacks(location b.Square) PieceAttacks {
	return this.attacks[location].pawnAttacks
}

// for every square and every attack direction permutation for slider attacks
// save all rays this piece is blocking
// usage: when we set/remove a piece, we need to adjust the attacks of the
// blocked rays
var blockedRays [b.H8 + 1][1 << 8][][]b.Square

func init() {

	// init blockedRays variable
	for square := b.A1; square <= b.H8; square++ {
		// step through every possible attack direction permutation
		for i := 0; i < 1<<8; i++ {
			// step through every single direction
			for j := uint(0); j < 8; j++ {
				if (i>>j)&0x1 == 1 {
					// there is an attack from this direction
					ray := []b.Square{}
					// get the opposite direction of the attack ray
					direction := -SlideDirections[j]
					for destination := square + direction; b.IsValidSquare(destination); destination += direction {
						ray = append(ray, destination)
					}
					if len(ray) > 0 {
						blockedRays[square][i] =
							append(blockedRays[square][i], ray)
					}
				}
			}
		}
	}

}

// todo: set attack directions
func (this *AttackBoard) SetPiece(p *pos.Position, piece pos.Piece, location b.Square) {

	// increase attack count for squares attacked by the set piece
	rays := &moveMatrix[piece.Type()][location]
	for i := range *rays {
		ray := (*rays)[i]
		// destBitmask := SliderIndexBitMasks[location-ray[0]]
		for j := range ray {
			destination := ray[j]
			this.attacks[destination].attacks++
			// todo this.SetDirection(destination, destBitmask)
			// destination occupied?
			if p.Piece(destination) != pos.NO_PIECE {
				break
			}
		}
	}

	// decrease slider attacks of squares blocked by the piece
	// todo: decrease number of slider attacks, this is only for all attacks
	// todo: remove direction bit from slider attack directions of this squares
	if this.NumberOfAttackers(location) > 0 {
		directions := blockedRays[location][this.SliderAttacks(location).directions]
		for i := range directions {
			for _, blockedSquare := range directions[i] {
				if this.NumberOfAttackers(blockedSquare) > 0 {
					this.attacks[blockedSquare].attacks--
				}
				if p.Piece(blockedSquare) != pos.NO_PIECE {
					// leave this ray, as there is a blocking piece
					break
				}
			}
		}
	}

}

func (this *AttackBoard) RemovePiece(piece pos.PieceType, location b.Square) {

}

// todo: maybe we can optimize some things when moving a slider
func (this *AttackBoard) MovePiece(piece pos.PieceType, from, to b.Square) {

}

func (this *AttackBoard) String() string {

	output := "\n"
	for rank := 8; rank > 0; rank-- {
		for file := b.A; file <= b.H; file++ {
			square, err := b.GetSquare(file, rank)
			if err != nil {
				panic(fmt.Sprintf("Invalid Square for file %v and rank %v", file, rank))
			}
			output += fmt.Sprintf("%d ", this.NumberOfAttackers(square))
		}
		output += fmt.Sprintln()
	}
	output += fmt.Sprintln()

	return output
}
*/
